home *** CD-ROM | disk | FTP | other *** search
- /*****************************************************************************
- * A decomposition of a Bspline curve into multi resolution hierarchy. *
- * *
- * Written by: Gershon Elber Ver 0.1, June 1993. *
- *****************************************************************************/
-
- #include "irit_sm.h"
- #include "cagd_lib.h"
- #include "symb_loc.h"
-
- #define MAX_AFFECTED_DIST 4.0
-
- /*****************************************************************************
- * DESCRIPTION: M
- * Given a Bspline curve, computes a hierarch of Bspline curves, each being M
- * represented using a subspace of the previous, upto a curve with no M
- * interior knots (i.e. a polynomial Bezier). M
- * However, if Discont == TRUE, then C1 discontinuities are preserved M
- * through out the hierarchy decomposition. M
- * Each level in hierarchy has approximately half the number of control M
- * points of the previous one. M
- * Least square curve fitting is used to build the hierarchy. M
- * *
- * PARAMETERS: M
- * Crv: To compute a least square multi resolution decomposition for. M
- * Discont: Do we want to preserve discontinuities? M
- * *
- * RETURN VALUE: M
- * SymbMultiResCrvStruct *: A multi resolution curve structure hold the M
- * multi resolution decomposition of Crv. M
- * *
- * KEYWORDS: M
- * SymbCrvMultiResDecomp, multi resolution, least square decomposition M
- *****************************************************************************/
- SymbMultiResCrvStruct *SymbCrvMultiResDecomp(CagdCrvStruct *Crv, int Discont)
- {
- CagdBType
- Periodic = CAGD_IS_PERIODIC_CRV(Crv);
- int KVListSize, *KVListSizes, i, j,
- Length = Crv -> Length,
- PrevLen = CAGD_CRV_PT_LST_LEN(Crv),
- Order = Crv -> Order,
- KVMaxSize = CAGD_CRV_PT_LST_LEN(Crv) + Order;
- CagdRType **KVList, *KVPtr, *Params,
- *KVPrev = Crv -> KnotVector;
- SymbMultiResCrvStruct *MRCrv;
- CagdCrvStruct *OCrv;
-
- if (!CAGD_IS_BSPLINE_CRV(Crv)) {
- SYMB_FATAL_ERROR(SYMB_ERR_BSP_CRV_EXPECT);
- return NULL;
- }
-
- /* Compute the hierarchy size and allocate its KnotVectors. */
- for (KVListSize = 0; (1 << KVListSize) < PrevLen - Order; KVListSize++);
- KVList = (CagdRType **) IritMalloc(sizeof(CagdRType *) * ++KVListSize);
- KVListSizes = (int *) IritMalloc(sizeof(int) * KVListSize);
-
- KVList[0] = (CagdRType *) IritMalloc(sizeof(CagdRType) * KVMaxSize);
- KVListSizes[0] = KVMaxSize;
- SYMB_GEN_COPY(KVList[0], KVPrev, sizeof(CagdRType) * KVMaxSize);
-
- for (i = 1; i < KVListSize; i++) {
- KVPtr = KVList[i] = (CagdRType *)
- IritMalloc(sizeof(CagdRType) * KVMaxSize);
-
- /* Copy first Order knots verbatim. */
- KVListSizes[i] = 2 * Order; /* End conditions are copied verbatim. */
- for (j = 0; j < Order; j++)
- *KVPtr++ = *KVPrev++;
-
- /* Skip every second interior knot. */
- for (; j < PrevLen; j++, KVPrev++) {
- if (Discont) {
- if ((j & 0x01) == 0 ||
- APX_EQ(KVPrev[-1], KVPrev[0]) ||
- APX_EQ(KVPrev[0], KVPrev[1])) {
- *KVPtr++ = *KVPrev;
- KVListSizes[i]++;
- }
- }
- else {
- if ((j & 0x01) == 0) {
- *KVPtr++ = *KVPrev;
- KVListSizes[i]++;
- }
- }
- }
-
- /* Copy last Order knots verbatim. */
- for (j = 0; j < Order; j++)
- *KVPtr++ = *KVPrev++;
-
- KVPrev = KVList[i];
- PrevLen = KVListSizes[i] - Order;
-
- /* Make sure we did not exhaust all the interior knots already, or */
- /* alternatively all interior knots maintains discontonuities. */
- if (Periodic ? PrevLen <= Order + Order - 1 : PrevLen <= Order) {
- KVListSize -= (KVListSize - i) - 1;
- if (Periodic ? PrevLen < Order + Order - 1 : PrevLen < Order) {
- IritFree(KVList[i]);
- KVListSize--;
- }
- break;
- }
- else if (KVListSizes[i] == KVListSizes[i-1]) {
- KVListSize -= KVListSize - i;
- IritFree(KVList[i]);
- break;
- }
- }
-
- if (Periodic) {
- /* Make sure spaces are consistent at the ends. */
- for (i = 0; i < KVListSize; i++) {
- int Len = KVListSizes[i] - Order;
- CagdRType
- *KV = KVList[i];
-
- for (j = 0; j < Order - 1; j++)
- KV[j] = KV[Order - 1] + KV[Len + j - (Order - 1)]
- - KV[Len];
- for (j = Len + 1; j < Len + Order; j++)
- KV[j] = KV[Len] + KV[j - Len + Order - 1] - KV[Order - 1];
- }
- }
-
- #ifdef DEBUG_PRINT_KVS
- for (i = 0; i < KVListSize; i++) {
- fprintf(stderr, "KV - LEVEL %d (len = %d) ***********************\n",
- i, KVListSizes[i]);
-
- for (j = 0; j < KVListSizes[i]; j++)
- fprintf(stderr, "%0.7lf ", KVList[i][j]);
- fprintf(stderr, "\n\n");
- }
- #endif /* DEBUG_PRINT_KVS */
-
- /* Now compute the curves in reverse, from the smallest subspace to the */
- /* largest and accumulate the representation upto the original space. */
- Params = CagdCrvNodes(Crv);
- MRCrv = SymbCrvMultiResNew(KVListSize, Periodic);
-
- if (!BspCrvHasOpenEC(Crv)) { /* We need an open end version of the curve. */
- if (Periodic) {
- CagdCrvStruct
- *TCrv = CnvrtPeriodic2FloatCrv(Crv);
-
- OCrv = CnvrtFloat2OpenCrv(TCrv);
- CagdCrvFree(TCrv);
- }
- else {
- OCrv = CnvrtFloat2OpenCrv(Crv);
- }
- }
- else
- OCrv = CagdCrvCopy(Crv);
-
- for (i = KVListSize - 1; i >= 0; i--) {
- CagdCrvStruct *InterpCrv, *DiffCrv;
- CagdCtlPtStruct
- *PtList = NULL;
-
- /* Sample the current curve at its node values to guarantee a */
- /* unique interpolatory result - identical to the original curve. */
- for (j = CAGD_CRV_PT_LST_LEN(OCrv) - 1; j >= 0; j--) {
- CagdCtlPtStruct
- *Pt = CagdCtlPtNew(OCrv -> PType);
- CagdRType
- *R = BspCrvEvalAtParam(OCrv, Params[j]);
-
- SYMB_GEN_COPY(Pt -> Coords, R,
- sizeof(CagdRType) * CAGD_MAX_PT_SIZE);
-
- Pt -> Pnext = PtList;
- PtList = Pt;
- }
-
- InterpCrv = BspCrvInterpolate(PtList, Length, Params, KVList[i],
- KVListSizes[i] - Order -
- (Periodic ? Order - 1 : 0),
- Order, Periodic);
- CagdCtlPtFreeList(PtList);
-
- if (!BspCrvHasOpenEC(InterpCrv)) {
- CagdCrvStruct *OInterpCrv;
-
- if (Periodic) {
- CagdCrvStruct
- *TCrv = CnvrtPeriodic2FloatCrv(InterpCrv);
-
- OInterpCrv = CnvrtFloat2OpenCrv(TCrv);
- CagdCrvFree(TCrv);
- }
- else {
- OInterpCrv = CnvrtFloat2OpenCrv(InterpCrv);
- }
-
- DiffCrv = SymbCrvSub(OCrv, OInterpCrv);
- MRCrv -> HieCrv[KVListSize - 1 - i] = OInterpCrv;
- CagdCrvFree(InterpCrv);
- }
- else {
- DiffCrv = SymbCrvSub(OCrv, InterpCrv);
- MRCrv -> HieCrv[KVListSize - 1 - i] = InterpCrv;
- }
-
- CagdCrvFree(OCrv);
- OCrv = DiffCrv;
- }
-
- CagdCrvFree(OCrv);
- IritFree((VoidPtr) Params);
-
- return MRCrv;
- }
-
- /*****************************************************************************
- * DESCRIPTION: M
- * Given a multi resolution decomposition of a Bspline curve, computes the M
- * regular Bspline curve out of it. *
- * M
- * *
- * PARAMETERS: M
- * MRCrv: A multi resolution decomposition of a curve. M
- * *
- * RETURN VALUE: M
- * CagdCrvStruct *: A curve that adds up all components of the multi M
- * resolution decomposition MRCrv. M
- * *
- * KEYWORDS: M
- * SymbCrvMultiResCompos, multi resolution, least square decomposition M
- *****************************************************************************/
- CagdCrvStruct *SymbCrvMultiResCompos(SymbMultiResCrvStruct *MRCrv)
- {
- return SymbCrvMultiResComposAtT(MRCrv,
- MRCrv -> Levels - 1 +
- (MRCrv -> RefineLevel != FALSE));
- }
-
- /*****************************************************************************
- * DESCRIPTION: M
- * Given a multi resolution decomposition of a Bspline curve, computes a M
- * regular Bspline curve out of it representing the decomposed curve at M
- * the multi resolution hierarchy level of T. M
- * Although decomposition is discrete, T can be any real number between M
- * these discrete levels and a linear interpolation of adjacent levels is M
- * exploited. M
- * *
- * PARAMETERS: M
- * MRCrv: A multi resolution decomposition of a curve. M
- * T: A mult resolution hierarcy level to compute curve for. M
- * *
- * RETURN VALUE: M
- * CagdCrvStruct *: A curve that adds up all components of the multi M
- * resolution decomposition MRCrv up to and including M
- * level T. M
- * *
- * KEYWORDS: M
- * SymbCrvMultiResComposAtT, multi resolution, least square decomposition M
- *****************************************************************************/
- CagdCrvStruct *SymbCrvMultiResComposAtT(SymbMultiResCrvStruct *MRCrv,
- CagdRType T)
- {
- int i,
- It = (int) T;
- CagdCrvStruct
- *SumCrv = CagdCrvCopy(MRCrv -> HieCrv[0]);
-
- for (i = 1;
- i <= It && i < MRCrv -> Levels + (MRCrv -> RefineLevel != FALSE);
- i++) {
- CagdCrvStruct
- *TCrv = SymbCrvAdd(SumCrv, MRCrv -> HieCrv[i]);
-
- CagdCrvFree(SumCrv);
- SumCrv = TCrv;
- }
-
- if (It != T) {
- CagdCrvStruct
- *TCrv1 = SymbCrvScalarScale(MRCrv -> HieCrv[It + 1], T - It),
- *TCrv2 = SymbCrvAdd(SumCrv, TCrv1);
-
- CagdCrvFree(TCrv1);
- CagdCrvFree(SumCrv);
- SumCrv = TCrv2;
- }
-
- return SumCrv;
- }
-
- /*****************************************************************************
- * DESCRIPTION: M
- * Given a multi resolution decomposition of a Bspline curve, edit it by M
- * modifying its Level'th Level according to the TransDir of Position at M
- * parametr t. M
- * Level can be a fraction number between the discrete levels of the M
- * decomposition denoting a linear blend of two neighboring discrete levels. M
- * Editing is performed in place. M
- * *
- * PARAMETERS: M
- * MRCrv: A multi resolution decomposition of a curve to edit it in M
- * place. M
- * t: Parameter value at which to modify MRCrv. M
- * TransDir: Directional tranlation transformation to apply. M
- * Level: Of multi resolution hierarchy to edit. M
- * FracLevel: The fraction level to edit - will blend two neighboring M
- * levels. M
- * SpanDiscont: Are we allowed to cross over discontinuities? M
- * *
- * RETURN VALUE: M
- * void M
- * *
- * KEYWORDS: M
- * SymbCrvMultiResEdit, multi resolution, least square decomposition M
- *****************************************************************************/
- void SymbCrvMultiResEdit(SymbMultiResCrvStruct *MRCrv,
- CagdRType t,
- CagdVType TransDir,
- CagdRType Level,
- CagdRType FracLevel)
- {
- int ILevel = (int) Level;
-
- if (Level == ILevel) {
- CagdCrvStruct *Crv, *OrigCrv, *DiffCrv;
- CagdRType *BasisFuncs, **Points;
- int i, Length, Order, IndexFirst;
-
- if (ILevel < 0 ||
- ILevel >= MRCrv -> Levels + (MRCrv -> RefineLevel != FALSE)) {
- SYMB_FATAL_ERROR(SYMB_ERR_OUT_OF_RANGE);
- return;
- }
-
- /* Prepare the Level'th curve in the hierarchy. */
- OrigCrv = CagdCrvCopy(MRCrv -> HieCrv[0]);
- for (i = 1; i <= ILevel; i++) {
- CagdCrvStruct
- *TCrv = SymbCrvAdd(OrigCrv, MRCrv -> HieCrv[i]);
-
- CagdCrvFree(OrigCrv);
- OrigCrv = TCrv;
- }
- Crv = CagdCrvCopy(OrigCrv);
-
- Points = Crv -> Points;
- Length = Crv -> Length;
- Order = Crv -> Order;
-
- BasisFuncs = BspCrvCoxDeBoorBasis(Crv -> KnotVector, Order,
- Length +
- (Crv -> Periodic ? Order - 1 : 0),
- t, &IndexFirst);
-
- for (i = IndexFirst; i < IndexFirst + Order; i++) {
- CagdRType
- MultFactor = BasisFuncs[i - IndexFirst];
-
- switch (Crv -> PType) {
- case CAGD_PT_E3_TYPE:
- Points[3][i] += TransDir[2] * MultFactor;
- case CAGD_PT_E2_TYPE:
- Points[2][i] += TransDir[1] * MultFactor;
- Points[1][i] += TransDir[0] * MultFactor;
- break;
- case CAGD_PT_P3_TYPE:
- case CAGD_PT_P2_TYPE:
- fprintf(stderr, "RATIONALS NOT SUPPORTED\n");
- exit(1);
- break;
- default:
- SYMB_FATAL_ERROR(SYMB_ERR_UNSUPPORT_PT);
- break;
- }
- }
-
- /* Construct the new hierarchy. */
- DiffCrv = SymbCrvSub(Crv, OrigCrv);
- CagdCrvFree(OrigCrv);
- CagdCrvFree(Crv);
-
- /* Apply the fraction ratio, if necessary. */
- if (!APX_EQ(FracLevel, 1.0)) {
- Crv = SymbCrvScalarScale(DiffCrv, FracLevel);
- CagdCrvFree(DiffCrv),
- DiffCrv = Crv;
- }
-
- Crv = SymbCrvAdd(MRCrv -> HieCrv[ILevel], DiffCrv);
- CagdCrvFree(MRCrv -> HieCrv[ILevel]);
- MRCrv -> HieCrv[ILevel] = Crv;
-
- CagdCrvFree(DiffCrv);
- }
- else {
- int Level1 = ILevel,
- Level2 = Level1 + 1;
-
- FracLevel = Level - Level1;
-
- SymbCrvMultiResEdit(MRCrv, t, TransDir, Level1,
- 1.0 - FracLevel),
- SymbCrvMultiResEdit(MRCrv, t, TransDir, Level2, FracLevel);
- }
- }
-
- /*****************************************************************************
- * DESCRIPTION: M
- * Given a multi resolution decomposition of a Bspline curve, refine it at M
- * neighborhood of parameter value t, in place. M
- * *
- * PARAMETERS: M
- * MRCrv: A multi resolution decomposition of a curve, to refine in M
- * place. M
- * T: Parameter value at which to refine MRCrv. M
- * SpanDiscont: Do we want to refine beyond discontinuities? M
- * *
- * RETURN VALUE: M
- * CagdRType *: A pointer to an array of two real numbers holding the M
- * domain in MRCrv that was refined. M
- * *
- * KEYWORDS: M
- * SymbCrvMultiResRefineLevel, multi resolution, least square decomposition M
- *****************************************************************************/
- CagdRType *SymbCrvMultiResRefineLevel(SymbMultiResCrvStruct *MRCrv,
- CagdRType T,
- int SpanDiscont)
- {
- static CagdRType Domain[2];
- CagdCrvStruct *Crv, *RefCrv;
- CagdRType TMin, TMax, **Points, *KV, *NewKV;
- int i, j, Order, Length, LastLIndex, FirstGIndex, StartIndex,
- NewKVIndex = 0;
-
- if (!MRCrv -> RefineLevel) {
- /* Do not have a refining level yet - add a zero valued curve now. */
- Crv = MRCrv -> HieCrv[MRCrv -> Levels] =
- CagdCrvCopy(MRCrv -> HieCrv[MRCrv -> Levels - 1]);
- Points = Crv -> Points;
- for (j = 0; j < Crv -> Length; j++)
- for (i = 1; i <= CAGD_NUM_OF_PT_COORD(Crv -> PType); i++)
- Points[i][j] = 0.0;
- MRCrv -> RefineLevel = TRUE;
- }
- else {
- Crv = MRCrv -> HieCrv[MRCrv -> Levels];
- }
- Length = Crv -> Length;
- Order = Crv -> Order;
-
- /* Figure out the knots to insert to the refining curve. */
- KV = Crv -> KnotVector;
- NewKV = (CagdRType *) IritMalloc(sizeof(CagdRType) * (Order + 1) * 2);
- CagdCrvDomain(Crv, &TMin, &TMax);
- LastLIndex = BspKnotLastIndexL(KV, Length + Order, T);
- FirstGIndex = BspKnotFirstIndexG(KV, Length + Order, T);
-
- /* Compute the new knots to the left. */
- for (StartIndex = 0, i = MAX(0, LastLIndex - Order);
- i <= LastLIndex;
- i++) {
- if (!APX_EQ(KV[i], KV[i + 1]))
- NewKV[NewKVIndex++] = (KV[i] + KV[i + 1]) / 2.0;
- else if (SpanDiscont)
- StartIndex = NewKVIndex;
- }
- /* Compute the new knots to the right. */
- for (i = FirstGIndex; i < MIN(FirstGIndex + Order, Length + Order); i++) {
- if (!APX_EQ(KV[i], KV[i + 1]))
- NewKV[NewKVIndex++] = (KV[i] + KV[i + 1]) / 2.0;
- else if (SpanDiscont)
- break;
- }
-
- #ifdef DEBUG_REFINE_KNOTS
- fprintf(stderr, "\nOld knot vector ********************\n");
- for (i = 0; i < Length + Order; i++)
- fprintf(stderr, "%8lg ", KV[i]);
- fprintf(stderr, "\nNew knots **************************\n");
- for (i = StartIndex; i < NewKVIndex; i++)
- fprintf(stderr, "%8lg ", NewKV[i]);
- #endif /* DEBUG_REFINE_KNOTS */
-
- Domain[0] = NewKV[StartIndex];
- Domain[1] = NewKV[NewKVIndex - 1];
- RefCrv = CagdCrvRefineAtParams(Crv, FALSE, &NewKV[StartIndex],
- NewKVIndex - StartIndex);
- IritFree((VoidPtr) NewKV);
-
- CagdCrvFree(MRCrv -> HieCrv[MRCrv -> Levels]);
- MRCrv -> HieCrv[MRCrv -> Levels] = RefCrv;
-
- return Domain;
- }
-
- /*****************************************************************************
- * DESCRIPTION: M
- * Given a multi resolution decomposition of a Bspline curve, free it. M
- * *
- * PARAMETERS: M
- * MRCrv: A multi resolution decomposition of a curve to free. M
- * *
- * RETURN VALUE: M
- * void M
- * *
- * KEYWORDS: M
- * SymbCrvMultiResFree, multi resolution, least square decomposition M
- *****************************************************************************/
- void SymbCrvMultiResFree(SymbMultiResCrvStruct *MRCrv)
- {
- int i;
-
- if (MRCrv == NULL)
- return;
-
- for (i = 0; i < MRCrv -> Levels + (MRCrv -> RefineLevel != FALSE); i++)
- CagdCrvFree(MRCrv -> HieCrv[i]);
-
- IritFree((VoidPtr) (MRCrv -> HieCrv));
- IritFree((VoidPtr) MRCrv);
- }
-
- /*****************************************************************************
- * DESCRIPTION: M
- * Allocates a data structure for multi resolution decomposition of a Bspline M
- * curve of Levels levels and possiblt periodic. M
- * *
- * PARAMETERS: M
- * Levels: Number of levels to expect in the decomposition. M
- * Periodic: Is the curve periodic? M
- * *
- * RETURN VALUE: M
- * SymbMultiResCrvStruct *: A structure to hold a multi resolution M
- * decomposition of a curve of Levels levels. M
- * *
- * KEYWORDS: M
- * SymbCrvMultiResNew, multi resolution, least square decomposition M
- *****************************************************************************/
- SymbMultiResCrvStruct *SymbCrvMultiResNew(int Levels, CagdBType Periodic)
- {
- SymbMultiResCrvStruct
- *MRCrv = (SymbMultiResCrvStruct *)
- IritMalloc(sizeof(SymbMultiResCrvStruct));
-
- MRCrv -> Levels = Levels;
-
- /* Keep one more level for the refining level to come. */
- MRCrv -> HieCrv = (CagdCrvStruct **)
- IritMalloc(sizeof(CagdCrvStruct *) * (Levels + 1));
-
- MRCrv -> RefineLevel = FALSE;
- MRCrv -> Periodic = Periodic;
- MRCrv -> Pnext = NULL;
-
- return MRCrv;
- }
- /*****************************************************************************
- * DESCRIPTION: M
- * Given a multi resolution decomposition of a Bspline curve, copy it. M
- * *
- * PARAMETERS: M
- * MRCrv: A multi resolution decomposition of a curve to copy. M
- * *
- * RETURN VALUE: M
- * SymbMultiResCrvStruct *: A duplicated structure of MRCrv. M
- * *
- * KEYWORDS: M
- * SymbCrvMultiResCopy, multi resolution, least square decomposition M
- *****************************************************************************/
- SymbMultiResCrvStruct *SymbCrvMultiResCopy(SymbMultiResCrvStruct *MRCrvOrig)
- {
- int i;
- SymbMultiResCrvStruct
- *MRCrv = (SymbMultiResCrvStruct *)
- IritMalloc(sizeof(SymbMultiResCrvStruct));
-
- MRCrv -> Levels = MRCrvOrig -> Levels;
- MRCrv -> RefineLevel = MRCrvOrig -> RefineLevel;
- MRCrv -> Pnext = NULL;
- MRCrv -> HieCrv = (CagdCrvStruct **) IritMalloc(sizeof(CagdCrvStruct *) *
- (MRCrvOrig -> Levels + 1));
-
- for (i = 0; i < MRCrv -> Levels + (MRCrv -> RefineLevel != FALSE); i++)
- MRCrv -> HieCrv[i] = CagdCrvCopy(MRCrvOrig -> HieCrv[i]);
-
-
- return MRCrv;
- }
-